#pragma once

#include "Socket.hpp"
#include "Inet_Addr.hpp"
#include "Connection.hpp"
#include "HanderConnection.hpp"

using namespace mySocket;

class listener
{
public:
    listener(uint16_t port, handerConnection &hr)
        : _port(port),
          _listenSock(new tcpSocket),
          _hr(hr)
    {
        _listenSock->tcpServerInit(InetAddr(_port));
    }

    // listener的读方法，这个conn就是listener自己
    // 由于listen套接字处于ET工作模式下，因此要循环读取
    // 根据errno决定读取是否完成
    void accepter(connection *conn)
    {
        while (true)
        {
            int code;
            InetAddr clientAddr;
            int sock = _listenSock->socketAccept(&clientAddr, &code);
            if (sock > 0)
            {
                // 向Reactor中添加连接
                conn->_r->addConnection(sock,
                                        EPOLLIN | EPOLLET,
                                        std::bind(&handerConnection::handlerRecver, &_hr, std::placeholders::_1),
                                        std::bind(&handerConnection::handlerSender, &_hr, std::placeholders::_1),
                                        std::bind(&handerConnection::handlerExcepter, &_hr, std::placeholders::_1));

                LOG(INFO, "accept fd: %d", sock);
            }
            else
            {
                if (code == EWOULDBLOCK || code == EAGAIN)
                {
                    LOG(INFO, "accept all link");
                    break;
                }
                else if (code == EINTR)
                    continue;
                else
                {
                    // 真的发生了错误
                    LOG(WORING, "accept error");
                    return;
                }
            }
        }
    }
    int getFd()
    {
        return _listenSock->getSockd();
    }
    ~listener()
    {
        _listenSock->socketClose();
    }

private:
    uint16_t _port;
    socket_ptr _listenSock;

    handerConnection &_hr;
};